home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / triangle.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  22.6 KB  |  765 lines

  1. /* $Id: triangle.c,v 1.17 1997/03/13 03:05:31 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: triangle.c,v $
  26.  * Revision 1.17  1997/03/13 03:05:31  brianp
  27.  * removed unused shift variable in feedback_triangle()
  28.  *
  29.  * Revision 1.16  1997/03/08 02:04:27  brianp
  30.  * better implementation of feedback function
  31.  *
  32.  * Revision 1.15  1997/03/04 18:54:13  brianp
  33.  * renamed mipmap_textured_triangle() to lambda_textured_triangle()
  34.  * better comments about lambda and mipmapping
  35.  *
  36.  * Revision 1.14  1997/02/20 23:47:35  brianp
  37.  * triangle feedback colors were wrong when using smooth shading
  38.  *
  39.  * Revision 1.13  1997/02/19 10:24:26  brianp
  40.  * use a GLdouble instead of a GLfloat for wwvvInv (perspective correction)
  41.  *
  42.  * Revision 1.12  1997/02/09 19:53:43  brianp
  43.  * now use TEXTURE_xD enable constants
  44.  *
  45.  * Revision 1.11  1997/02/09 18:51:02  brianp
  46.  * added GL_EXT_texture3D support
  47.  *
  48.  * Revision 1.10  1997/01/16 03:36:43  brianp
  49.  * added #include "texture.h"
  50.  *
  51.  * Revision 1.9  1997/01/09 19:50:49  brianp
  52.  * now call gl_texturing_enabled()
  53.  *
  54.  * Revision 1.8  1996/12/20 20:23:30  brianp
  55.  * the test for using general_textured_triangle() was wrong
  56.  *
  57.  * Revision 1.7  1996/12/12 22:37:30  brianp
  58.  * projective textures didn't work right
  59.  *
  60.  * Revision 1.6  1996/11/08 02:21:21  brianp
  61.  * added null drawing function for GL_NO_RASTER
  62.  *
  63.  * Revision 1.5  1996/10/01 03:31:17  brianp
  64.  * use new FixedToDepth() macro
  65.  *
  66.  * Revision 1.4  1996/09/27 01:30:37  brianp
  67.  * removed unneeded INTERP_ALPHA from flat_rgba_triangle()
  68.  *
  69.  * Revision 1.3  1996/09/15 14:19:16  brianp
  70.  * now use GLframebuffer and GLvisual
  71.  *
  72.  * Revision 1.2  1996/09/15 01:48:58  brianp
  73.  * removed #define NULL 0
  74.  *
  75.  * Revision 1.1  1996/09/13 01:38:16  brianp
  76.  * Initial revision
  77.  *
  78.  */
  79.  
  80.  
  81. /*
  82.  * Triangle rasterizers
  83.  */
  84.  
  85.  
  86. #include <assert.h>
  87. #include <math.h>
  88. #include <stdio.h>
  89. #include "depth.h"
  90. #include "feedback.h"
  91. #include "macros.h"
  92. #include "span.h"
  93. #include "texture.h"
  94. #include "triangle.h"
  95. #include "types.h"
  96. #include "vb.h"
  97.  
  98.  
  99.  
  100. /*
  101.  * Put triangle in feedback buffer.
  102.  */
  103. static void feedback_triangle( GLcontext *ctx,
  104.                                GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  105. {
  106.    struct vertex_buffer *VB = ctx->VB;
  107.    GLfloat color[4];
  108.    GLuint i;
  109.    GLfloat invRedScale   = ctx->Visual->InvRedScale;
  110.    GLfloat invGreenScale = ctx->Visual->InvGreenScale;
  111.    GLfloat invBlueScale  = ctx->Visual->InvBlueScale;
  112.    GLfloat invAlphaScale = ctx->Visual->InvAlphaScale;
  113.  
  114.    FEEDBACK_TOKEN( ctx, (GLfloat) GL_POLYGON_TOKEN );
  115.    FEEDBACK_TOKEN( ctx, (GLfloat) 3 );        /* three vertices */
  116.  
  117.    if (ctx->Light.ShadeModel==GL_FLAT) {
  118.       /* flat shading - same color for each vertex */
  119.       color[0] = (GLfloat) VB->Color[pv][0] * invRedScale;
  120.       color[1] = (GLfloat) VB->Color[pv][1] * invGreenScale;
  121.       color[2] = (GLfloat) VB->Color[pv][2] * invBlueScale;
  122.       color[3] = (GLfloat) VB->Color[pv][3] * invAlphaScale;
  123.    }
  124.  
  125.    for (i=0;i<3;i++) {
  126.       GLfloat x, y, z, w;
  127.       GLfloat tc[4];
  128.       GLuint v;
  129.       GLfloat invq;
  130.  
  131.       if (i==0)       v = v0;
  132.       else if (i==1)  v = v1;
  133.       else            v = v2;
  134.  
  135.       x = VB->Win[v][0];
  136.       y = VB->Win[v][1];
  137.       z = VB->Win[v][2] / DEPTH_SCALE;
  138.       w = VB->Clip[v][3];
  139.  
  140.       if (ctx->Light.ShadeModel==GL_SMOOTH) {
  141.          /* smooth shading - different color for each vertex */
  142.          color[0] = FixedToFloat(VB->Color[v][0]) * invRedScale;
  143.          color[1] = FixedToFloat(VB->Color[v][1]) * invGreenScale;
  144.          color[2] = FixedToFloat(VB->Color[v][2]) * invBlueScale;
  145.          color[3] = FixedToFloat(VB->Color[v][3]) * invAlphaScale;
  146.       }
  147.  
  148.       invq = 1.0F / VB->TexCoord[v][3];
  149.       tc[0] = VB->TexCoord[v][0] * invq;
  150.       tc[1] = VB->TexCoord[v][1] * invq;
  151.       tc[2] = VB->TexCoord[v][2] * invq;
  152.       tc[3] = VB->TexCoord[v][3];
  153.  
  154.       gl_feedback_vertex( ctx, x, y, z, w, color, (GLfloat) VB->Index[v], tc );
  155.    }
  156. }
  157.  
  158.  
  159.  
  160. /*
  161.  * Put triangle in selection buffer.
  162.  */
  163. static void select_triangle( GLcontext *ctx,
  164.                              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  165. {
  166.    struct vertex_buffer *VB = ctx->VB;
  167.  
  168.    gl_update_hitflag( ctx, VB->Win[v0][2] / DEPTH_SCALE );
  169.    gl_update_hitflag( ctx, VB->Win[v1][2] / DEPTH_SCALE );
  170.    gl_update_hitflag( ctx, VB->Win[v2][2] / DEPTH_SCALE );
  171. }
  172.  
  173.  
  174.  
  175. /*
  176.  * Render a flat-shaded color index triangle.
  177.  */
  178. static void flat_ci_triangle( GLcontext *ctx,
  179.                               GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  180. {
  181. #define INTERP_Z 1
  182.  
  183. #define SETUP_CODE                \
  184.    GLuint index = VB->Index[pv];        \
  185.    if (!VB->MonoColor) {            \
  186.       /* set the color index */            \
  187.       (*ctx->Driver.Index)( ctx, index );    \
  188.    }
  189.  
  190. #define INNER_LOOP( LEFT, RIGHT, Y )                \
  191.     {                            \
  192.        GLint i, n = RIGHT-LEFT;                \
  193.        GLdepth zspan[MAX_WIDTH];                \
  194.        if (n>0) {                        \
  195.           for (i=0;i<n;i++) {                \
  196.          zspan[i] = FixedToDepth(ffz);            \
  197.          ffz += fdzdx;                    \
  198.           }                            \
  199.           gl_write_monoindex_span( ctx, n, LEFT, Y,        \
  200.                                 zspan, index, GL_POLYGON );    \
  201.        }                            \
  202.     }
  203.  
  204. #include "tritemp.h"          
  205. }
  206.  
  207.  
  208.  
  209. /*
  210.  * Render a smooth-shaded color index triangle.
  211.  */
  212. static void smooth_ci_triangle( GLcontext *ctx,
  213.                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  214. {
  215. #define INTERP_Z 1
  216. #define INTERP_INDEX 1
  217.  
  218. #define INNER_LOOP( LEFT, RIGHT, Y )                \
  219.     {                            \
  220.        GLint i, n = RIGHT-LEFT;                \
  221.        GLdepth zspan[MAX_WIDTH];                \
  222.            GLuint index[MAX_WIDTH];                \
  223.        if (n>0) {                        \
  224.           for (i=0;i<n;i++) {                \
  225.          zspan[i] = FixedToDepth(ffz);            \
  226.                  index[i] = FixedToInt(ffi);            \
  227.          ffz += fdzdx;                    \
  228.          ffi += fdidx;                    \
  229.           }                            \
  230.           gl_write_index_span( ctx, n, LEFT, Y, zspan,    \
  231.                                index, GL_POLYGON );        \
  232.        }                            \
  233.     }
  234.  
  235. #include "tritemp.h"
  236. }
  237.  
  238.  
  239.  
  240. /*
  241.  * Render a flat-shaded RGBA triangle.
  242.  */
  243. static void flat_rgba_triangle( GLcontext *ctx,
  244.                                 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  245. {
  246. #define INTERP_Z 1
  247.  
  248. #define SETUP_CODE                \
  249.    if (!VB->MonoColor) {            \
  250.       /* set the color */            \
  251.       GLubyte r = VB->Color[pv][0];        \
  252.       GLubyte g = VB->Color[pv][1];        \
  253.       GLubyte b = VB->Color[pv][2];        \
  254.       GLubyte a = VB->Color[pv][3];        \
  255.       (*ctx->Driver.Color)( ctx, r, g, b, a );    \
  256.    }
  257.  
  258. #define INNER_LOOP( LEFT, RIGHT, Y )                \
  259.     {                            \
  260.        GLint i, n = RIGHT-LEFT;                \
  261.        GLdepth zspan[MAX_WIDTH];                \
  262.        if (n>0) {                        \
  263.           for (i=0;i<n;i++) {                \
  264.          zspan[i] = FixedToDepth(ffz);            \
  265.          ffz += fdzdx;                    \
  266.           }                            \
  267.               gl_write_monocolor_span( ctx, n, LEFT, Y, zspan,    \
  268.                              VB->Color[pv][0], VB->Color[pv][1],\
  269.                              VB->Color[pv][2], VB->Color[pv][3],\
  270.                  GL_POLYGON );            \
  271.        }                            \
  272.     }
  273.  
  274. #include "tritemp.h"
  275. }
  276.  
  277.  
  278.  
  279. /*
  280.  * Render a smooth-shaded RGBA triangle.
  281.  */
  282. static void smooth_rgba_triangle( GLcontext *ctx,
  283.                                   GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  284. {
  285. #define INTERP_Z 1
  286. #define INTERP_RGB 1
  287. #define INTERP_ALPHA 1
  288.  
  289. #define INNER_LOOP( LEFT, RIGHT, Y )                \
  290.     {                            \
  291.        GLint i, n = RIGHT-LEFT;                \
  292.        GLdepth zspan[MAX_WIDTH];                \
  293.        GLubyte red[MAX_WIDTH], green[MAX_WIDTH];        \
  294.        GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];        \
  295.        if (n>0) {                        \
  296.           for (i=0;i<n;i++) {                \
  297.          zspan[i] = FixedToDepth(ffz);            \
  298.          red[i]   = FixedToInt(ffr);            \
  299.          green[i] = FixedToInt(ffg);            \
  300.          blue[i]  = FixedToInt(ffb);            \
  301.          alpha[i] = FixedToInt(ffa);            \
  302.          ffz += fdzdx;                    \
  303.          ffr += fdrdx;                    \
  304.          ffg += fdgdx;                    \
  305.          ffb += fdbdx;                    \
  306.          ffa += fdadx;                    \
  307.           }                            \
  308.           gl_write_color_span( ctx, n, LEFT, Y, zspan,    \
  309.                                red, green, blue, alpha,    \
  310.                    GL_POLYGON );        \
  311.        }                            \
  312.     }
  313.  
  314. #include "tritemp.h"
  315. }
  316.  
  317.  
  318.  
  319. /*
  320.  * Render an RGB, GL_DECAL, textured triangle.
  321.  * Interpolate S,T only w/out mipmapping or perspective correction.
  322.  */
  323. static void simple_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  324.                                       GLuint v2, GLuint pv )
  325. {
  326. #define INTERP_ST 1
  327. #define S_SCALE twidth
  328. #define T_SCALE theight
  329. #define SETUP_CODE                            \
  330.    GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;    \
  331.    GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\
  332.    GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2;    \
  333.    GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data;        \
  334.    GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1;        \
  335.    GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1;
  336.  
  337. #define INNER_LOOP( LEFT, RIGHT, Y )                \
  338.     {                            \
  339.        GLint i, n = RIGHT-LEFT;                \
  340.        GLubyte red[MAX_WIDTH], green[MAX_WIDTH];        \
  341.        GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];        \
  342.        if (n>0) {                        \
  343.           for (i=0;i<n;i++) {                \
  344.                  GLint s = FixedToInt(ffs) & smask;        \
  345.                  GLint t = FixedToInt(fft) & tmask;        \
  346.                  GLint pos = (t << twidth_log2) + s;        \
  347.                  pos = pos + pos  + pos;  /* multiply by 3 */    \
  348.                  red[i]   = texture[pos];            \
  349.                  green[i] = texture[pos+1];            \
  350.                  blue[i]  = texture[pos+2];            \
  351.                  alpha[i] = 255;                \
  352.          ffs += fdsdx;                    \
  353.          fft += fdtdx;                    \
  354.           }                            \
  355.               (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y,    \
  356.                              red, green, blue, alpha, NULL );    \
  357.        }                            \
  358.     }
  359.  
  360. #include "tritemp.h"
  361. }
  362.  
  363.  
  364.  
  365. /*
  366.  * Render an RGB, GL_DECAL, textured triangle.
  367.  * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
  368.  * perspective correction.
  369.  */
  370. static void simple_z_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  371.                                       GLuint v2, GLuint pv )
  372. {
  373. #define INTERP_Z 1
  374. #define INTERP_ST 1
  375. #define S_SCALE twidth
  376. #define T_SCALE theight
  377. #define SETUP_CODE                            \
  378.    GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;    \
  379.    GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\
  380.    GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2;    \
  381.    GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data;        \
  382.    GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1;        \
  383.    GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1;
  384.  
  385. #define INNER_LOOP( LEFT, RIGHT, Y )                \
  386.     {                            \
  387.        GLint i, n = RIGHT-LEFT;                \
  388.        GLubyte red[MAX_WIDTH], green[MAX_WIDTH];        \
  389.        GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];        \
  390.            GLubyte mask[MAX_WIDTH];                \
  391.        if (n>0) {                        \
  392.           for (i=0;i<n;i++) {                \
  393.                  GLdepth z = FixedToDepth(ffz);            \
  394.                  if (z < zRow[i]) {                \
  395.                     GLint s = FixedToInt(ffs) & smask;        \
  396.                     GLint t = FixedToInt(fft) & tmask;        \
  397.                     GLint pos = (t << twidth_log2) + s;        \
  398.                     pos = pos + pos  + pos;  /* multiply by 3 */\
  399.                     red[i]   = texture[pos];            \
  400.                     green[i] = texture[pos+1];            \
  401.                     blue[i]  = texture[pos+2];            \
  402.                     alpha[i] = 255;                \
  403.             zRow[i] = z;                \
  404.                     mask[i] = 1;                \
  405.                  }                        \
  406.                  else {                        \
  407.                     mask[i] = 0;                \
  408.                  }                        \
  409.          ffz += fdzdx;                    \
  410.          ffs += fdsdx;                    \
  411.          fft += fdtdx;                    \
  412.           }                            \
  413.               (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y,    \
  414.                              red, green, blue, alpha, mask );    \
  415.        }                            \
  416.     }
  417.  
  418. #include "tritemp.h"
  419. }
  420.  
  421.  
  422.  
  423. /*
  424.  * Render a smooth-shaded, textured, RGBA triangle.
  425.  * Interpolate S,T,U with perspective correction, w/out mipmapping.
  426.  * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
  427.  * R is already used for red.
  428.  */
  429. static void general_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  430.                                        GLuint v2, GLuint pv )
  431. {
  432. #define INTERP_Z 1
  433. #define INTERP_RGB 1
  434. #define INTERP_ALPHA 1
  435. #define INTERP_STW 1
  436. #define INTERP_UV 1
  437. #define SETUP_CODE                        \
  438.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);    \
  439.    GLint r, g, b, a;                        \
  440.    if (flat_shade) {                        \
  441.       r = VB->Color[pv][0];                    \
  442.       g = VB->Color[pv][1];                    \
  443.       b = VB->Color[pv][2];                    \
  444.       a = VB->Color[pv][3];                    \
  445.    }
  446. #define INNER_LOOP( LEFT, RIGHT, Y )                \
  447.     {                            \
  448.        GLint i, n = RIGHT-LEFT;                \
  449.        GLdepth zspan[MAX_WIDTH];                \
  450.        GLubyte red[MAX_WIDTH], green[MAX_WIDTH];        \
  451.        GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];        \
  452.            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];    \
  453.        if (n>0) {                        \
  454.               if (flat_shade) {                    \
  455.                  for (i=0;i<n;i++) {                \
  456.             GLdouble wwvvInv = 1.0 / (ww*vv);        \
  457.             zspan[i] = FixedToDepth(ffz);        \
  458.             red[i]   = r;                \
  459.             green[i] = g;                \
  460.             blue[i]  = b;                \
  461.             alpha[i] = a;                \
  462.             s[i] = ss*wwvvInv;                \
  463.             t[i] = tt*wwvvInv;                \
  464.             u[i] = uu*wwvvInv;                \
  465.             ffz += fdzdx;                \
  466.             ss += dsdx;                    \
  467.             tt += dtdx;                    \
  468.             uu += dudx;                    \
  469.             vv += dvdx;                    \
  470.             ww += dwdx;                    \
  471.          }                        \
  472.               }                            \
  473.               else {                        \
  474.                  for (i=0;i<n;i++) {                \
  475.             GLdouble wwvvInv = 1.0 / (ww*vv);        \
  476.             zspan[i] = FixedToDepth(ffz);        \
  477.             red[i]   = FixedToInt(ffr);            \
  478.             green[i] = FixedToInt(ffg);            \
  479.             blue[i]  = FixedToInt(ffb);            \
  480.             alpha[i] = FixedToInt(ffa);            \
  481.             s[i] = ss*wwvvInv;                \
  482.             t[i] = tt*wwvvInv;                \
  483.             u[i] = uu*wwvvInv;                \
  484.             ffz += fdzdx;                \
  485.             ffr += fdrdx;                \
  486.             ffg += fdgdx;                \
  487.             ffb += fdbdx;                \
  488.             ffa += fdadx;                \
  489.             ss += dsdx;                    \
  490.             tt += dtdx;                    \
  491.             uu += dudx;                    \
  492.             ww += dwdx;                    \
  493.             vv += dvdx;                    \
  494.          }                        \
  495.               }                            \
  496.           gl_write_texture_span( ctx, n, LEFT, Y, zspan,    \
  497.                                      s, t, u, NULL,         \
  498.                                  red, green, blue, alpha,    \
  499.                      GL_POLYGON );        \
  500.        }                            \
  501.     }
  502.  
  503. #include "tritemp.h"
  504. }
  505.  
  506.  
  507.  
  508. /*
  509.  * Compute the lambda (texture level value) for a fragment.
  510.  */
  511. static GLfloat compute_lambda( GLfloat s, GLfloat t,
  512.                                GLfloat dsdx, GLfloat dsdy,
  513.                                GLfloat dtdx, GLfloat dtdy,
  514.                                GLfloat w,
  515.                                GLfloat width, GLfloat height )
  516. {
  517.    /* TODO: this function can probably be optimized a bit */
  518.    GLfloat invw = 1.0F / w;
  519.    GLfloat s0, t0, s1, t1, s2, t2;
  520.    GLfloat dudx, dudy, dvdx, dvdy;
  521.    GLfloat r1, r2, rho;
  522.  
  523.    s0 = s * invw;
  524.    t0 = t * invw;
  525.    s1 = (s+dsdx) * invw;
  526.    t1 = (t+dtdx) * invw;
  527.    s2 = (s+dsdy) * invw;
  528.    t2 = (t+dtdy) * invw;
  529.  
  530.    dudx = (s1-s0) * width;
  531.    dudy = (s2-s0) * width;
  532.    dvdx = (t1-t0) * height;
  533.    dvdy = (t2-t0) * height;
  534.  
  535.    /* r1 = sqrt( dudx * dudx + dvdx * dvdx ); */
  536.    /* r2 = sqrt( dudy * dudy + dvdy * dvdy ); */
  537.    if (dudx<0.0F)  dudx = -dudx;
  538.    if (dudy<0.0F)  dudy = -dudy;
  539.    if (dvdx<0.0F)  dvdx = -dvdx;
  540.    if (dvdy<0.0F)  dvdy = -dvdy;
  541.    r1 = MAX2( dudx, dudy );
  542.    r2 = MAX2( dvdx, dvdy );
  543.    rho = MAX2(r1,r2);
  544.  
  545.    if (rho<=0.0F) {
  546.       return 0.0F;
  547.    }
  548.    else {
  549.       /* return log base 2 of rho */
  550.       return log(rho) * 1.442695;       /* 1.442695 = 1/log(2) */
  551.    }
  552. }
  553.  
  554.  
  555.  
  556. /*
  557.  * Render a smooth-shaded, textured, RGBA triangle.
  558.  * Interpolate S,T,U with perspective correction and compute lambda for
  559.  * each fragment.  Lambda is used to determine whether to use the
  560.  * minification or magnification filter.  If minification and using
  561.  * mipmaps, lambda is also used to select the texture level of detail.
  562.  */
  563. static void lambda_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  564.                                       GLuint v2, GLuint pv )
  565. {
  566. #define INTERP_Z 1
  567. #define INTERP_RGB 1
  568. #define INTERP_ALPHA 1
  569. #define INTERP_STW 1
  570. #define INTERP_UV 1
  571.  
  572. #define SETUP_CODE                            \
  573.    GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT);        \
  574.    GLint r, g, b, a;                            \
  575.    GLfloat twidth, theight;                        \
  576.    if (ctx->Texture.Enabled & TEXTURE_3D) {                \
  577.       twidth = (GLfloat) ctx->Texture.Current3D->Image[0]->Width;    \
  578.       theight = (GLfloat) ctx->Texture.Current3D->Image[0]->Height;    \
  579.    }                                    \
  580.    else if (ctx->Texture.Enabled & TEXTURE_2D) {            \
  581.       twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width;    \
  582.       theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;    \
  583.    }                                    \
  584.    else {                                \
  585.       twidth = (GLfloat) ctx->Texture.Current1D->Image[0]->Width;    \
  586.       theight = 1.0;                            \
  587.    }                                    \
  588.    if (flat_shade) {                            \
  589.       r = VB->Color[pv][0];                        \
  590.       g = VB->Color[pv][1];                        \
  591.       b = VB->Color[pv][2];                        \
  592.       a = VB->Color[pv][3];                        \
  593.    }
  594.  
  595. #define INNER_LOOP( LEFT, RIGHT, Y )                    \
  596.     {                                \
  597.        GLint i, n = RIGHT-LEFT;                    \
  598.        GLdepth zspan[MAX_WIDTH];                    \
  599.        GLubyte red[MAX_WIDTH], green[MAX_WIDTH];            \
  600.        GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH];            \
  601.            GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];        \
  602.            GLfloat lambda[MAX_WIDTH];                    \
  603.        if (n>0) {                            \
  604.           if (flat_shade) {                        \
  605.          for (i=0;i<n;i++) {                    \
  606.             GLdouble wwvvInv = 1.0 / (ww*vv);            \
  607.             zspan[i] = FixedToDepth(ffz);            \
  608.             red[i]   = r;                    \
  609.             green[i] = g;                    \
  610.             blue[i]  = b;                    \
  611.             alpha[i] = a;                    \
  612.             s[i] = ss*wwvvInv;                    \
  613.             t[i] = tt*wwvvInv;                    \
  614.             u[i] = uu*wwvvInv;                    \
  615.             lambda[i] = compute_lambda( s[i], t[i],        \
  616.                         dsdx, dsdy,        \
  617.                         dtdx, dtdy, ww,        \
  618.                         twidth, theight );    \
  619.             ffz += fdzdx;                    \
  620.             ss += dsdx;                        \
  621.             tt += dtdx;                        \
  622.             uu += dudx;                        \
  623.             vv += dvdx;                        \
  624.             ww += dwdx;                        \
  625.          }                            \
  626.               }                                \
  627.               else {                            \
  628.          for (i=0;i<n;i++) {                    \
  629.             GLdouble wwvvInv = 1.0 / (ww*vv);            \
  630.             zspan[i] = FixedToDepth(ffz);            \
  631.             red[i]   = FixedToInt(ffr);                \
  632.             green[i] = FixedToInt(ffg);                \
  633.             blue[i]  = FixedToInt(ffb);                \
  634.             alpha[i] = FixedToInt(ffa);                \
  635.             s[i] = ss*wwvvInv;                    \
  636.             t[i] = tt*wwvvInv;                    \
  637.             u[i] = uu*wwvvInv;                    \
  638.             lambda[i] = compute_lambda( s[i], t[i],        \
  639.                         dsdx, dsdy,        \
  640.                         dtdx, dtdy, ww,        \
  641.                         twidth, theight );    \
  642.             ffz += fdzdx;                    \
  643.             ffr += fdrdx;                    \
  644.             ffg += fdgdx;                    \
  645.             ffb += fdbdx;                    \
  646.             ffa += fdadx;                    \
  647.             ss += dsdx;                        \
  648.             tt += dtdx;                        \
  649.             uu += dtdx;                        \
  650.             vv += dvdx;                        \
  651.             ww += dwdx;                        \
  652.          }                            \
  653.               }                                \
  654.           gl_write_texture_span( ctx, n, LEFT, Y, zspan,        \
  655.                                      s, t, u, lambda,             \
  656.                                  red, green, blue, alpha,        \
  657.                      GL_POLYGON );            \
  658.        }                                \
  659.     }
  660.  
  661. #include "tritemp.h"
  662. }
  663.  
  664.  
  665.  
  666. /*
  667.  * Null rasterizer for measuring transformation speed.
  668.  */
  669. static void null_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
  670.                            GLuint v2, GLuint pv )
  671. {
  672. }
  673.  
  674.  
  675.  
  676. /*
  677.  * Determine which triangle rendering function to use given the current
  678.  * rendering context.
  679.  */
  680. void gl_set_triangle_function( GLcontext *ctx )
  681. {
  682.    GLboolean rgbmode = ctx->Visual->RGBAflag;
  683.  
  684.    if (ctx->RenderMode==GL_RENDER) {
  685.       if (ctx->NoRaster) {
  686.          ctx->TriangleFunc = null_triangle;
  687.          return;
  688.       }
  689.       if (ctx->Driver.TriangleFunc) {
  690.          /* Device driver will draw triangles. */
  691.          ctx->TriangleFunc = ctx->Driver.TriangleFunc;
  692.       }
  693.       else if (gl_texturing_enabled(ctx)) {
  694.          if (   (ctx->Texture.Enabled==TEXTURE_2D)
  695.              && ctx->Texture.Current2D->Complete
  696.              && ctx->Texture.Current2D->MinFilter==GL_NEAREST
  697.              && ctx->Texture.Current2D->MagFilter==GL_NEAREST
  698.              && ctx->Texture.Current2D->WrapS==GL_REPEAT
  699.              && ctx->Texture.Current2D->WrapT==GL_REPEAT
  700.              && ctx->Texture.Current2D->Image[0]->Format==GL_RGB
  701.              && ctx->Texture.Current2D->Image[0]->Border==0
  702.              && (ctx->Texture.EnvMode==GL_DECAL
  703.                  || ctx->Texture.EnvMode==GL_REPLACE)
  704.              && ctx->Hint.PerspectiveCorrection==GL_FASTEST
  705.              && ctx->IdentityTexMat
  706.              && (ctx->RasterMask==DEPTH_BIT || ctx->RasterMask==0)
  707.              && ctx->Depth.Func==GL_LESS
  708.              && ctx->Depth.Mask==GL_TRUE
  709.              && ctx->Polygon.StippleFlag==GL_FALSE
  710.              && ctx->Visual->EightBitColor) {
  711.             if (ctx->RasterMask==DEPTH_BIT) {
  712.                ctx->TriangleFunc = simple_z_textured_triangle;
  713.             }
  714.             else {
  715.                ctx->TriangleFunc = simple_textured_triangle;
  716.             }
  717.          }
  718.          else {
  719.             GLboolean needLambda = GL_TRUE;
  720.             /* if mag filter == min filter we're not mipmapping */
  721.             if (ctx->Texture.Enabled & TEXTURE_3D) {
  722.                if (ctx->Texture.Current3D->MinFilter==
  723.                    ctx->Texture.Current3D->MagFilter) {
  724.                   needLambda = GL_FALSE;
  725.                }
  726.         }
  727.             else if (ctx->Texture.Enabled & TEXTURE_2D) {
  728.                if (ctx->Texture.Current2D->MinFilter==
  729.                    ctx->Texture.Current2D->MagFilter) {
  730.                   needLambda = GL_FALSE;
  731.                }
  732.             }
  733.             else if (ctx->Texture.Enabled & TEXTURE_1D) {
  734.                if (ctx->Texture.Current1D->MinFilter==
  735.                    ctx->Texture.Current1D->MagFilter) {
  736.                   needLambda = GL_FALSE;
  737.                }
  738.             }
  739.             ctx->TriangleFunc = needLambda ? lambda_textured_triangle
  740.                                            : general_textured_triangle;
  741.          }
  742.       }
  743.       else {
  744.      if (ctx->Light.ShadeModel==GL_SMOOTH) {
  745.         /* smooth shaded, no texturing, stippled or some raster ops */
  746.         ctx->TriangleFunc = rgbmode ? smooth_rgba_triangle
  747.                                         : smooth_ci_triangle;
  748.      }
  749.      else {
  750.         /* flat shaded, no texturing, stippled or some raster ops */
  751.         ctx->TriangleFunc = rgbmode ? flat_rgba_triangle
  752.                                         : flat_ci_triangle;
  753.      }
  754.       }
  755.    }
  756.    else if (ctx->RenderMode==GL_FEEDBACK) {
  757.       ctx->TriangleFunc = feedback_triangle;
  758.    }
  759.    else {
  760.       /* GL_SELECT mode */
  761.       ctx->TriangleFunc = select_triangle;
  762.    }
  763. }
  764.  
  765.